package main

import (
	"encoding/json"
	"fmt"
	"io"
	"math/rand"
	"os"
	"path"
	"time"

	"github.com/cloudwebrtc/go-protoo/logger"
	"github.com/pion/webrtc/v2"
	"github.com/pion/webrtc/v2/pkg/media"
	"github.com/pion/webrtc/v2/pkg/media/h264reader"
	"github.com/pion/webrtc/v2/pkg/media/ivfreader"
	"github.com/pion/webrtc/v2/pkg/media/oggreader"
)

var (
	//ivfReader
	//oggReader
	duration int
)

func (t *Trans) writeVideoToTrack(filename string) {
	_, err := os.Stat(filename)
	haveVideoFile := !os.IsNotExist(err)

	if haveVideoFile == false {
		return
	}

	//sp := strings.Split(filename, ".")
	ext := path.Ext(filename)
	if ext == ".ivf" {
		pubTrans.writeIvfToTrack(filename)
	} else {
		pubTrans.writeH264ToTrack(filename)
	}
}

func (t *Trans) writeH264ToTrack(filename string) {
	var err error
	peerConnection := t.pc
	// Create a video track
	videoTrack, addTrackErr := peerConnection.NewTrack(webrtc.DefaultPayloadTypeH264, rand.Uint32(), "video", "pion")
	if addTrackErr != nil {
		panic(addTrackErr)
	}
	if _, addTrackErr = peerConnection.AddTrack(videoTrack); err != nil {
		panic(addTrackErr)
	}

	go func() {
		// Open a H264 file and start reading using our H264Reader
		file, h264Err := os.Open(filename)
		if h264Err != nil {
			panic(h264Err)
		}

		defer file.Close()

		reader, h264Err := h264reader.NewReader(file)
		if h264Err != nil {
			panic(h264Err)
		}

		if useCtx {
			<-iceConnectedCtx.Done()
		} else {
			<-t.iceConnected
		}

		//sleepTime := time.Millisecond * time.Duration((float32(header.TimebaseNumerator)/float32(header.TimebaseDenominator))*1000)
		sleepTime := time.Millisecond * time.Duration(40)
		for {
			fmt.Println("h264 frames parsed and sent")
			nal, h264Err := reader.NextNAL()
			if h264Err == io.EOF {
				fmt.Printf("All video frames parsed and sent")
				peerConnection.Close()
				os.Exit(0)
			}

			if h264Err != nil {
				panic(h264Err)
			}

			time.Sleep(sleepTime)
			if h264Err = videoTrack.WriteSample(media.Sample{Data: nal.Data, Samples: 90000}); h264Err != nil {
				panic(h264Err)
			}
		}
	}()
}

// Read a video file from disk and write it to a webrtc.Track
// When the video has been completely read this exits without error
//func writeVideoToTrack(t *webrtc.TrackLocalStaticSample) {
func (t *Trans) writeIvfToTrack(filename string) {
	var err error
	peerConnection := t.pc
	// Create a video track
	videoTrack, addTrackErr := peerConnection.NewTrack(webrtc.DefaultPayloadTypeVP8, rand.Uint32(), "video", "pion")
	if addTrackErr != nil {
		panic(addTrackErr)
	}
	if _, addTrackErr = peerConnection.AddTrack(videoTrack); err != nil {
		panic(addTrackErr)
	}

	go func() {
		// Open a IVF file and start reading using our IVFReader
		file, ivfErr := os.Open(filename)
		if ivfErr != nil {
			panic(ivfErr)
		}

		ivf, header, ivfErr := ivfreader.NewWith(file)
		if ivfErr != nil {
			panic(ivfErr)
		}

		if useCtx {
			<-iceConnectedCtx.Done()
		} else {
			<-t.iceConnected
		}

		sleepTime := time.Millisecond * time.Duration((float32(header.TimebaseNumerator)/float32(header.TimebaseDenominator))*1000)
		for {
			frame, _, ivfErr := ivf.ParseNextFrame()
			if ivfErr == io.EOF {
				fmt.Printf("All video frames parsed and sent")
				peerConnection.Close()
				os.Exit(0)
			}

			if ivfErr != nil {
				panic(ivfErr)
			}

			time.Sleep(sleepTime)
			if ivfErr = videoTrack.WriteSample(media.Sample{Data: frame, Samples: 90000}); ivfErr != nil {
				panic(ivfErr)
			}
		}
	}()
}

func (t *Trans) writeAudioToTrack(filename string) {
	// Open a Ogg file and start reading using our IVFReader
	peerConnection := t.pc
	_, err := os.Stat(filename)
	haveAudioFile := !os.IsNotExist(err)
	fmt.Println("check audio file")
	if haveAudioFile {
		fmt.Println("has audio file")
		// Create a audio track
		audioTrack, addTrackErr := peerConnection.NewTrack(webrtc.DefaultPayloadTypeOpus, rand.Uint32(), "audio", "pion")
		if addTrackErr != nil {
			panic(addTrackErr)
		}
		if _, addTrackErr = peerConnection.AddTrack(audioTrack); err != nil {
			panic(addTrackErr)
		}

		go func() {
			// Open a IVF file and start reading using our IVFReader
			file, oggErr := os.Open(filename)
			if oggErr != nil {
				panic(oggErr)
			}

			// Open on oggfile in non-checksum mode.
			ogg, _, oggErr := oggreader.NewWith(file)
			if oggErr != nil {
				panic(oggErr)
			}

			// Wait for connection established
			if useCtx {
				<-iceConnectedCtx.Done()
			} else {
				<-t.iceConnected
			}

			// Keep track of last granule, the difference is the amount of samples in the buffer
			var lastGranule uint64
			for {
				pageData, pageHeader, oggErr := ogg.ParseNextPage()
				if oggErr == io.EOF {
					fmt.Printf("All audio pages parsed and sent")
					os.Exit(0)
				}

				if oggErr != nil {
					panic(oggErr)
				}

				// The amount of samples is the difference between the last and current timestamp
				sampleCount := float64((pageHeader.GranulePosition - lastGranule))
				sampleCount = 960
				lastGranule = pageHeader.GranulePosition
				fmt.Printf("sent a audio frame start sampleCount %d dataLen %d\n", uint32(sampleCount), len(pageData))
				if oggErr = audioTrack.WriteSample(media.Sample{Data: pageData, Samples: uint32(sampleCount)}); oggErr != nil {
					panic(oggErr)
				}
				// Convert seconds to Milliseconds, Sleep doesn't accept floats
				//time.Sleep(time.Duration((sampleCount/48000)*1000) * time.Millisecond)
				time.Sleep(20 * time.Millisecond)
			}
		}()
	}
}

func (t *Trans) subscrible() {
	peerConnection := t.pc
	offer, err := peerConnection.CreateOffer(nil)
	if err != nil {
		panic(err)
	}

	mysubscribedata := make(map[string]interface{})
	mysubjsep := make(map[string]interface{})
	mysubjsep["type"] = "offer"
	mysubjsep["sdp"] = offer.SDP
	mysubscribedata["rid"] = roomid
	mysubscribedata["mid"] = mid //
	mysubscribedata["jsep"] = mysubjsep
	peer.Request("subscribe", mysubscribedata,
		func(result map[string]interface{}) {
			//logger.Infof("subscribe success: =>  %s", result)
			logger.Infof("subscribe success: =>  ")
			//logger.Infof("subscribe success receive jsep: =>  %+v", result["jsep"])

			str_sub, err := json.Marshal(result["jsep"])
			if err != nil {
				fmt.Println(err)
			}
			var mysubjsep string = string(str_sub)
			var subscribe_xjsep mJsep
			json.Unmarshal([]byte(mysubjsep), &subscribe_xjsep)
			//fmt.Println("subscribe sdp:"+subscribe_xjsep.Sdp)
			//fmt.Println("subscribe type:"+subscribe_xjsep.Type)

			err = peerConnection.SetRemoteDescription(webrtc.SessionDescription{
				Type: webrtc.SDPTypeAnswer,
				SDP:  subscribe_xjsep.Sdp,
			})
			if err != nil {
				panic(err)
			}

		},
		func(code int, err string) {
			logger.Infof("subscribe reject: %d => %s", code, err)
		})
}

func (t *Trans) unsubscrible() {
	myunsubscribedata := make(map[string]interface{})
	myunsubscribedata["rid"] = roomid
	myunsubscribedata["mid"] = mid
	//peer.Request("unsubscribe", JsonEncode(`{"rid":"room1","mid":"87a8d77d-d72b-4aac-ba8e-6f4688fb9e30"}`),
	peer.Request("unsubscribe", myunsubscribedata,
		func(result map[string]interface{}) {
			logger.Infof("unsubscribe success: =>  %s", result)
		},
		func(code int, err string) {
			logger.Infof("unsubscribe reject: %d => %s", code, err)
		})
}
